/*
 * Copyright (c) 2017, www.zm0618.com All Rights Reserved..
 */

package com.light.hessian.remoting.client.core;

import com.caucho.hessian.client.HessianProxyFactory;
import com.light.hessian.remoting.client.config.ClientConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ClassUtils;

import java.net.MalformedURLException;

/**
 * Created by zhaojun on 2017/02/10.
 */
public class ProxyObjectBuilder {


    private ClientConfig clientConfig;

    private Class serviceInterface;

    private String serviceName;

    private HessianProxyFactory proxyFactory = new HessianProxyFactory();

    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    /**
     * <p>Author:zhaojun;</p>
     * <p>Date:2016年4月9日下午1:55:54;</p>
     * <p>Description: TODO;</p>
     */
    public ProxyObjectBuilder(ClientConfig clientConfig, Class serviceInterface, String serviceName) {
        this.clientConfig = clientConfig;
        this.proxyFactory.setSerializerFactory(clientConfig.getSerializerFactory());
        this.proxyFactory.setConnectTimeout(clientConfig.getConnectTimeout());
        this.proxyFactory.setReadTimeout(clientConfig.getReadTimeout());
        this.proxyFactory.setOverloadEnabled(clientConfig.isOverloadEnabled());
        this.proxyFactory.setUser(clientConfig.getUsername());
        this.proxyFactory.setPassword(clientConfig.getPassword());
        this.proxyFactory.setDebug(clientConfig.isDebug());
        this.proxyFactory.setChunkedPost(clientConfig.isChunkedPost());
        this.proxyFactory.setConnectionFactory(clientConfig.getConnectionFactory());
        this.setSendCollectionType(clientConfig.isSendCollectionType());
        this.setAllowNonSerializable(clientConfig.isAllowNonSerializable());
        this.serviceInterface = serviceInterface;
        this.serviceName = serviceName;
    }


    public Object build() throws MalformedURLException {
        String host = this.getClientConfig().getHost();
        String servicePath = StringUtils.join(new String[]{host, serviceName}, host.charAt(host.length() - 1) == '/' ? "" : "/");
        return this.proxyFactory.create(this.serviceInterface, servicePath, beanClassLoader);
    }


    /**
     * Set whether to send the Java collection type for each serialized
     * collection. Default is "true".
     */
    public void setSendCollectionType(boolean sendCollectionType) {
        this.proxyFactory.getSerializerFactory().setSendCollectionType(sendCollectionType);
    }

    /**
     * Set whether to allow non-serializable types as Hessian arguments
     * and return values. Default is "true".
     */
    public void setAllowNonSerializable(boolean allowNonSerializable) {
        this.proxyFactory.getSerializerFactory().setAllowNonSerializable(allowNonSerializable);
    }


    /**
     * Set whether version 2 of the Hessian protocol should be used for
     * parsing requests and replies. Default is "false".
     *
     * @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Request
     */
    public void setHessian2(boolean hessian2) {

        this.proxyFactory.setHessian2Request(hessian2);
        this.proxyFactory.setHessian2Reply(hessian2);
    }

    /**
     * Set whether version 2 of the Hessian protocol should be used for
     * parsing requests. Default is "false".
     *
     * @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Request
     */
    public void setHessian2Request(boolean hessian2) {
        this.proxyFactory.setHessian2Request(hessian2);
    }

    /**
     * Set whether version 2 of the Hessian protocol should be used for
     * parsing replies. Default is "false".
     *
     * @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Reply
     */
    public void setHessian2Reply(boolean hessian2) {
        this.proxyFactory.setHessian2Reply(hessian2);
    }

    /**
     * @return the clientConfig
     */
    public ClientConfig getClientConfig() {
        return clientConfig;
    }

    /**
     * @param clientConfig clientConfig
     */
    public void setClientConfig(ClientConfig clientConfig) {
        this.clientConfig = clientConfig;
    }

}


